#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: ystlong
# @Date:   2018-06-29 03:59:19
# @Last Modified by:   long
# @Last Modified time: 2018-06-28 21:09:42
import os
import sys

# // $FN_NAME
# // $ARG_LIST_DEF
# // $ARG_NAME_LIST
# // $IS_RETURN
# // $RETURN_TYPE
hold_tpl_file = "hold_tpl.c"

def gen_fn(fn_def):
	return_type = fn_def.strip().split()[0]
	fn_name = fn_def.split('(')[0].split()[1]
	args_list_def = fn_def[fn_def.index('(')+1:fn_def.rindex(")")]
	args_list = []
	if args_list_def.strip() == "void" or args_list_def.strip() == "":
		pass
	else:
		for args in args_list_def.split(","):
			if args.split(")")[0].find("(") > 0:
				# 参数为函数指针
				arg_name = args.split(")")[0].split("(")[1].split("*")[1].strip()
			else:
				arg_name = args.strip().strip('[]').strip().split()[-1].split("*")[-1].strip();
			args_list.append(arg_name)
	is_return = "return"
	if return_type == "void":
		is_return = ""
	arg_name_list = ", ".join(args_list)
	return (fn_name, args_list_def, arg_name_list, is_return, return_type)

def gen_c_file(fn_infs, out_name):
	out_c_name = "auto_gen_%s-hold.c"%(out_name)
	with open(out_c_name, "w") as ofs:
		with open(hold_tpl_file) as f:
			tpl_lines = []
			start_tpl = False
			for line in f:
				if line.startswith("// {hold_start}"):
					start_tpl = True
				elif line.startswith("// {hold_end}"):
					for fn_info in fn_infs:
						fn_name = fn_info[0]
						args_list_def = fn_info[1]
						arg_name_list = fn_info[2]
						is_return = fn_info[3]
						return_type = fn_info[4]
						for line in tpl_lines:
							line = line.replace("$FN_NAME", fn_name)
							line = line.replace("$ARG_LIST_DEF", args_list_def)
							line = line.replace("$ARG_NAME_LIST", arg_name_list)
							line = line.replace("$IS_RETURN", is_return)
							line = line.replace("$RETURN_TYPE", return_type)
							ofs.write(line)
					start_tpl = False
					tpl_lines = []
				elif start_tpl == True:
					tpl_lines.append(line)
				else:
					ofs.write(line)

	compiler_cmd = "gcc -shared -fPIC %s -o %s-hold.so"%(out_c_name, out_name)
	print "complie: %s"%(compiler_cmd)
	os.system(compiler_cmd)

fn_infs = []

# fn_infs.append(gen_fn("void exit(int code)"))
fn_infs.append(gen_fn("pid_t fork(void)"))
fn_infs.append(gen_fn("pid_t vfork(void)"))
fn_infs.append(gen_fn("int clone(int (*fn)(void *), void *child_stack,int flags, void *arg)"))

       # int execl(const char *path, const char *arg0, ... /*, (char *)0 */);                                                                                                                     
       # int execle(const char *path, const char *arg0, ... /*,(char *)0, char *const envp[]*/);                                                                                                                                                    
       # int execlp(const char *file, const char *arg0, ... /*, (char *)0 */);                                                                                                                    
       # int execv(const char *path, char *const argv[]);                                                                                                                                         
       # int execve(const char *path, char *const argv[], char *const envp[]);                                                                                                                    
       # int execvp(const char *file, char *const argv[]);                                                                                                                                        
       # int fexecve(int fd, char *const argv[], char *const envp[]); 

gen_c_file(fn_infs, "verdi")
